#include <cmath>
#include <cstdio>
#include <iostream>
#include "black_scholes_vs.h"
#include "mcnormal_vs.h"
#include "variance_swap.h"

using namespace std;

VarianceSwap::VarianceSwap()
{
	_spot_price = 1156.15;
	_maturity = 1.62;
	_risk_free_rate = 0.0498;
}

VarianceSwap::VarianceSwap(double spotPrice, double riskFreeRate, double maturity)
{
	_spot_price = spotPrice;
	_maturity = maturity;
	_risk_free_rate = riskFreeRate;
}

void VarianceSwap::vs_readData(char* input)
{
	FILE* fp = fopen(input, "r");
	
	double strike, sigma;
	
	while (fscanf(fp, "%lf %lf", &strike, &sigma) != EOF) {
		_strike_price.push_back(strike);
		_volatility.push_back(sigma);
	}

	fclose(fp);
}

double VarianceSwap::computeFutureValue()
{
	return _spot_price*exp(_risk_free_rate*_maturity);
}

double 
VarianceSwap::computeOptionPrice
(int type, double strike_price, double sigma)
{
	return BlackScholes(type, _spot_price, strike_price, sigma,
							 _maturity, _risk_free_rate, 0);	
}

double VarianceSwap::getVarianceSwap()
{
	vector<double> contribution;
	double price;
	double future_value;
	double vs_value = 0;

	future_value = computeFutureValue();

	// find the index that separate Call and Put
	int index = 0;

	while (_strike_price[index] < future_value)
		index++;

	// type == 0
	for (int i = 0; i < index; i++) {
		price = computeOptionPrice(0, _strike_price[i], _volatility[i]);
		// cout << "the price is:  " << price << endl;  
		double delta_put = _strike_price[i+1] - _strike_price[i];
		double contribution = 1/(_strike_price[i]*_strike_price[i])*price*delta_put;
		// cout << "The value added: " << contribution << endl ;
		vs_value += 1/(_strike_price[i]*_strike_price[i])*price*delta_put;
	}

	// after future_value: use call option
	// type == 1
	for (int i = index - 1; i < _strike_price.size(); i++) {
		price = computeOptionPrice(1, _strike_price[i], _volatility[i]);
		// cout << "the price is:  " << price << endl;  
		double delta_call = _strike_price[i] - _strike_price[i-1];
		double contribution = 1/(_strike_price[i]*_strike_price[i])*price*delta_call;
		// cout << "The value added: " << contribution << endl ;
		vs_value += 1/(_strike_price[i]*_strike_price[i])*price*delta_call;
	}

	vs_value *= 2/_maturity; 

	return vs_value;
}

void VarianceSwap::vs_printDebug()
{
	cout << "The spot price is: " << _spot_price << endl;
	cout << "The risk free rate is: " << _risk_free_rate << endl;
	cout << "The maturity is: " << _maturity << endl; 
	cout << "The future value (computed by computeFutureValue()): " 
		 << computeFutureValue() << endl;

	/*
	for (int i = 0; i < _strike_price.size(); i++)
		cout << "This is strike price: " << _strike_price[i] << endl;

	for (int i = 0; i < _volatility.size(); i++)
		cout << "This is volatility: " << _volatility[i] << endl;
	*/
}
